package woaini.wind.bot.command.qylc.app.ticket.cmd;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONPath;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import woaini.wind.bot.command.qylc.app.ticket.api.CenterApi;
import woaini.wind.bot.command.qylc.app.ticket.api.QylcTicketApi;
import woaini.wind.bot.command.qylc.app.ticket.document.FaceRequestLog;
import woaini.wind.bot.command.qylc.app.ticket.service.QylcTicketService;
import woaini.wind.bot.core.command.ICmd;
import woaini.wind.bot.core.command.anno.CmdParams;
import woaini.wind.bot.core.command.anno.SubCmd;
import woaini.wind.bot.core.event.segment.Messages;
import woaini.wind.bot.core.exception.BotAssertTool;
import woaini.wind.bot.core.exception.enums.BotExceptionType;
import woaini.wind.bot.core.session.Session;

import java.util.List;

/**
 * 票务系统api
 *
 * @see QylcTicketCmd
 * @author yefeng {@date 2025-06-12 11:04:22}
 */
@Component
@RequiredArgsConstructor
public class QylcTicketCmd implements ICmd {

  private final QylcTicketService qylcTicketService;

  private final MongoTemplate mongoTemplate;

  @Override
  public String masterCmdName() {
    return "票务";
  }

  @Override
  public String description() {
    return "票务系统相关的命令";
  }

  @SubCmd("订单分析")
  public void orderVoucher(
      Session session,
      @CmdParams(value = "c", description = "证件号", required = true) String cardNo) {

    String searchTicket = QylcTicketApi.searchTicket(cardNo);

    BotAssertTool.isActualTrue(
        StrUtil.isEmpty(searchTicket), BotExceptionType.BOT_SERVICE, "订单查询失败!!");

    Integer totalElements = Convert.toInt(JSONPath.extract(searchTicket, "$.data.totalElements"));
    if (totalElements == 0) {
      session.replyMessage(Messages.builder().text("票务系统没有查询到可用订单"));
      //获取中台订单存在嘛  存在查看状态和是否需要审核
      String searchedResourcesOrderInfo = CenterApi.searchResourcesOrderInfo(cardNo);
      BotAssertTool.isActualTrue(
          StrUtil.isEmpty(searchedResourcesOrderInfo), BotExceptionType.BOT_SERVICE, "中台订单查询失败!!");

      totalElements = Convert.toInt(JSONPath.extract(searchedResourcesOrderInfo, "$.totalElements"));
      BotAssertTool.isActualTrue(totalElements == 0, BotExceptionType.BOT_SERVICE, "中台未查询到有效资源订单!!");

      //获取中台套票订单存在嘛
    }else {
      //存在订单展示凭证信息
      String masterOrderNo =
        Convert.toStr(JSONPath.extract(searchTicket, "$.data.content[0].masterOrderNo"));

      // 获取凭证信息
      String voucherInfo = QylcTicketApi.getVoucherInfo(masterOrderNo, cardNo);

      BotAssertTool.isActualTrue(
        StrUtil.isEmpty(voucherInfo), BotExceptionType.BOT_SERVICE, "凭证信息获取异常!!");


      String path = STR."$.data.vouches[?(@.vouchExtInfo=='\{cardNo}')][0]";

      JSONObject masterVoucher = (JSONObject) JSONPath.extract(voucherInfo, path);
      if (masterVoucher == null) {
        session.replyMessage(Messages.builder().text("票务系统没有查询到凭证信息"));
      }

      // 获取凭证
      String vouchCode = masterVoucher.getString("vouchCode");
      if (vouchCode.startsWith("SS")){
        session.replyMessage(Messages.builder().text(voucherTemplate(masterVoucher)));
      }else {
        //获取子凭证信息
        String subVoucherInfo = QylcTicketApi.getSubVoucherInfo(vouchCode);
        BotAssertTool.isActualTrue(
          StrUtil.isEmpty(subVoucherInfo), BotExceptionType.BOT_SERVICE, "子凭证信息获取异常!!");

        JSONArray subVoucherCodeArrays = (JSONArray) JSONPath.extract(subVoucherInfo, "$.data.content");
        for (int i = 0; i < subVoucherCodeArrays.size(); i++) {
          JSONObject iSubVoucherInfo = subVoucherCodeArrays.getJSONObject(i);
          session.replyMessage(Messages.builder().text(voucherTemplate(iSubVoucherInfo)));
        }
      }
    }
  }

  @SubCmd("检票分析")
  public void run(
    Session session,
    @CmdParams(value = "c", description = "证件号", required = true) String cardNo) {

    String gatePassSituation = QylcTicketApi.gatePassSituationByCardNo(cardNo);
    BotAssertTool.isActualTrue(
        StrUtil.isEmpty(gatePassSituation), BotExceptionType.BOT_SERVICE, "过闸分析获取异常!!");

    JSONArray gatePassSituationLogArrays = (JSONArray) JSONPath.extract(gatePassSituation, "$.content");

    if  (gatePassSituationLogArrays.isEmpty()) {
      session.replyMessage(Messages.builder().text(STR."\{cardNo}无过闸信息,设备未请求到票务,初步分析为闸机人脸识别不过,或者刷身份证异常!!"));
    }else {

      //存在过闸的情况
      JSONObject first = gatePassSituationLogArrays.getJSONObject(0);
      String createTime = first.getString("createTime");
      Boolean success = first.getBoolean("success");
      if (success) {
        String modName = first.getString("modName");
        if (modName.equals("紫鹏查验票")){
          session.replyMessage(Messages.builder().text(STR."\{cardNo}查票无异常,进行检票分析,时间:\{createTime}"));
          this.ticketInspectionAnalysis(session,cardNo);
          return;
        }
      }
      String responseBody = first.getString("responseBody");
      if (StrUtil.isNotBlank(responseBody)){
        JSONObject responseBodyJson = JSONObject.parseObject(responseBody);
        String errorMsg = responseBodyJson.getString("msg");
        Integer code = responseBodyJson.getInteger("code");
        session.replyMessage(Messages.builder().text(STR."\{cardNo}最近一次过闸失败,code=\{code}错误提示:\{errorMsg}"));
        return;
      }
      String requestBody = first.getString("requestBody");
      JSONObject requestBodyJson = JSONObject.parseObject(requestBody);

      String errorStack = first.getString("errorStack");

      if (errorStack.contains("请刷人脸通行")){
        session.replyMessage(Messages.builder().text(STR."\{cardNo}提示刷脸通行,正在进行检票分析"));
        this.ticketInspectionAnalysis(session,cardNo);
        return;
      }

      if (errorStack.contains("无效二维码")){
        //获取二维码字段
        String qrcode = requestBodyJson.getString("qrCode");
        session.replyMessage(Messages.builder().text(STR."二维码过闸失败,目前只支持S开头的凭证,当前凭证为:\{qrcode}"));
      }
      session.replyMessage(Messages.builder().text("未知异常,请及时查看处理"));
    }

  }

  @SubCmd("测试单")
  public void testOrder(
    Session session,
    @CmdParams(value = "c", description = "证件号", required = true) String cardNo,
    @CmdParams(value = "n", description = "姓名", required = true) String name,
    @CmdParams(value = "ct", description = "证件类型") String cardType,
    @CmdParams(value = "s", description = "景区 黄 龙 屯 格") String scenic,
    @CmdParams(value = "code", description = "授权码") String authCode) {

    if (StrUtil.isNotEmpty(scenic)){
        switch (scenic){
          case "黄":
          {
            authCode ="TR100142891261734";
            break;
          }
          case "龙":
          {
            authCode ="TR106682252143329";
            break;
          }
          case "屯":{
            session.replyMessage(Messages.builder().text("目前没有屯"));
            return;
          }
          case "格":{
           authCode ="TR108433052088671";
           break;
          }
          default:
            break;
        }
    }

    if (StrUtil.isEmpty(authCode)){
      authCode ="TR100142891261734";
    }
    if (StrUtil.isEmpty(cardType)){
      cardType = "ID";
    }

    String masterOrderInfo = QylcTicketApi.createTestOrder(name, cardNo,authCode,cardType);
    BotAssertTool.isActualTrue(
      StrUtil.isEmpty(masterOrderInfo), BotExceptionType.BOT_SERVICE, "创建测试单异常!!");
    // 主订单号获取
    String masterOrderNo = JSONPath.extract(masterOrderInfo, "$.data.orderNo").toString();

    session.replyMessage(Messages.builder().text(STR."创建测试单成功,订单号:\{masterOrderNo}"));
    //成功的情况下 付款订单
    QylcTicketApi.payTestOrder(masterOrderNo);
    session.replyMessage(Messages.builder().text(STR."订单付款成功,订单号:\{masterOrderNo}"));
  }


  /**
   * 检票分析 也就是在查票后需要进行分析的情况
   * 比如查票没问题 或者提示人脸
   * @param cardNo 卡号
   * @author yefeng
   * {@date 2025-06-12 14:32:14}
   * @since 1.0
   *
   */
  public void ticketInspectionAnalysis(Session session,String cardNo){

    //正常的情况下 获取凭证信息
    List<String> voucherCodes = qylcTicketService.getVoucherInfo(cardNo);
    BotAssertTool.isActualTrue(
      CollUtil.isEmpty(voucherCodes), BotExceptionType.BOT_SERVICE, "未查询到对应的凭证信息!!");

    for (String voucherCode : voucherCodes) {
      //使用凭证查询
      String gatePassSituation = QylcTicketApi.gatePassSituationByVoucher(voucherCode);
      BotAssertTool.isActualTrue(
        StrUtil.isEmpty(gatePassSituation), BotExceptionType.BOT_SERVICE, "获取核验信息异常!!");
      JSONArray gatePassSituationLogArrays1 = (JSONArray) JSONPath.extract(gatePassSituation, "$.content");
      if (gatePassSituationLogArrays1.isEmpty()){
        continue;
      }
      JSONObject jsonObject = gatePassSituationLogArrays1.getJSONObject(0);

      String createTime = jsonObject.getString("createTime");
      Boolean success = jsonObject.getBoolean("success");
      if (success){
        session.replyMessage(Messages.builder().text(STR."\{cardNo}最近一次过闸成功无异常,时间:\{createTime}"));
        return;
      }
      String responseBody = jsonObject.getString("responseBody");
      String errorStack = jsonObject.getString("errorStack");

      if (StrUtil.isEmpty(responseBody) || responseBody.contains("请重新采集人脸")){

        Query query = new Query();
        query.addCriteria(Criteria.where("vid").is(cardNo));

        Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
        query.with(sort);
        PageRequest pageRequest = PageRequest.of(0, 3);
        query.with(pageRequest);

        List<FaceRequestLog> faceRequestLogs = mongoTemplate.find(query, FaceRequestLog.class);
        if (CollUtil.isEmpty(faceRequestLogs)){
          session.replyMessage(Messages.builder().text(STR."\{cardNo}设备未进行人脸采集,可能是识别阈值低"));
          return;
        }else {
          FaceRequestLog faceRequestLog = faceRequestLogs.get(0);
          String faceRequestLogResponseBody = faceRequestLog.getResponseBody();
          String errorMsg = ReUtil.get("[\u4e00-\u9fa5]+",faceRequestLogResponseBody,  0);

          session.replyMessage(Messages.builder().text(STR."\{cardNo}最近一次人脸采集失败,时间:\{faceRequestLog.getCreateTime()},原因:\{errorMsg}"));
          return;
        }
      }else{
        //正则匹配中文
        String errorMsg = ReUtil.get( "[\u4e00-\u9fa5]+",errorStack, 0);
        session.replyMessage(Messages.builder().text(STR."\{cardNo}最近一次过闸失败,时间:\{createTime}错误提示:\{errorMsg}"));
      }
    }
    session.replyMessage(Messages.builder().text(STR."\{cardNo}未查询到检票记录,可能是设备识别匹配失败"));
  }

  private String voucherTemplate(JSONObject voucherInfo){

    String vouchCode = voucherInfo.getString("vouchCode");
    String orderStatusStr;
    if (vouchCode.startsWith("SS")){
      orderStatusStr= voucherInfo.getString("orderStatusStr");
    }else {
      orderStatusStr = voucherInfo.getString("orderStatusComment");
    }
    String travelDate = voucherInfo.getString("travelDate");
      String vouchEffectiveStockTime = voucherInfo.getString("vouchEffectiveStockTime");
    String vouchEffectiveTime = voucherInfo.getString("vouchEffectiveTime");
      String vouchExpirationTime = voucherInfo.getString("vouchExpirationTime");
    String ticketName = voucherInfo.getString("ticketName");
    String vouchExtName = voucherInfo.getString("vouchExtName");
      String vouchExtInfo = voucherInfo.getString("vouchExtInfo");


    return
      STR."""
      凭证信息:
      用户信息: \{vouchExtName}-\{vouchExtInfo}
      票名称: \{ticketName}
      凭证码: \{vouchCode}
      凭证状态: \{orderStatusStr}
      游玩时间: \{travelDate}
      游玩时段:  \{vouchEffectiveStockTime}
      有效期时间: \{vouchEffectiveTime}-\{vouchExpirationTime}
    """;
  }

  @SubCmd("人脸出库")
  public void zfbOutFace(
    Session session,
    @CmdParams(value = "c", description = "证件号", required = true) String cardNo) {

      QylcTicketApi.zfbOutFace(cardNo);
      session.replyMessage(Messages.builder().text(STR."\{cardNo}出库成功"));
  }
}
